/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.core.actions;
import java.io.Serializable;
import java.awt.MenuShortcut;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.List;
import java.util.Set;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.event.*;
import javax.swing.JMenuItem;
import org.netbeans.core.windows.ModeImpl;
import org.netbeans.core.windows.WorkspaceImpl;
import org.netbeans.core.windows.WindowManagerImpl;
import org.openide.TopManager;
import org.openide.windows.Mode;
import org.openide.windows.TopComponent;
import org.openide.windows.Workspace;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.*;
import org.openide.awt.*;
/** Dock the top component to the mode.
*
* @author Dafe Simonek
*/
public final class DockingAction extends CallableSystemAction {
/** Implementation of ActSubMenuInt */
private static ActSubMenuModel model;
/* constant special items in docking menu */
static final SpecialItem NEW_SINGLE_ITEM = new SpecialItem(
NbBundle.getBundle(DockingAction.class).getString("CTL_NewSingle"),
ModeImpl.SINGLE
);
static final SpecialItem NEW_MULTI_TAB_ITEM = new SpecialItem(
NbBundle.getBundle(DockingAction.class).getString("CTL_NewMultiTab"),
ModeImpl.MULTI_TAB
);
/** name of new multi tab mode when docking to it */
static final String newMultiTabName =
NbBundle.getBundle(DockingAction.class).getString("CTL_NewMultiTabName");
/** asociation with window manager implementation */
static WindowManagerImpl wm =
(WindowManagerImpl)TopManager.getDefault().getWindowManager();
/* Constructs a new docking action */
static final long serialVersionUID =8679037289261745865L;
public DockingAction() {
}
/* Returns resource string pointing to actions' icon.
* @return resource string of actions' icon
*/
protected String iconResource () {
return "/org/netbeans/core/resources/actions/dock.gif"; // NOI18N
}
public HelpCtx getHelpCtx() {
return new HelpCtx (DockingAction.class);
}
/* @return Returns localized name of this action */
public String getName() {
return NbBundle.getBundle(DockingAction.class).getString("Docking");
}
/* Returns a submenu that will presents this action in menu bar
* @return the JMenuItem representation for this action (which is submenu)
*/
public JMenuItem getMenuPresenter() {
return new SpecialSubMenu(this, getModel(), false);
}
/* Returns a submneu that will present this action in a PopupMenu.
* @return the JMenuItem representation for this action
*/
public JMenuItem getPopupPresenter() {
return new SpecialSubMenu(this, getModel(), true);
}
/* Actually performs the "docking" action by setting the mode
* of how component will be displayed
*/
public void performAction () {
// all functionality is accomplished by
// ActSubMenuModel.performActionAt(int)
}
/** Convenience method for obtaining submenu model */
static ActSubMenuModel getModel () {
if (model == null)
model = new ActSubMenuModel();
return model;
}
/** SubMenu of this action - notifies data model about
* ancestor changes (addNotify, removeNotify)
*/
private static final class SpecialSubMenu extends Actions.SubMenu {
static final long serialVersionUID =-3808638464776612755L;
SpecialSubMenu (SystemAction aAction, Actions.SubMenuModel model,
boolean popup) {
super(aAction, model, popup);
}
/** Notifies data model in adition to normal behaviour */
public void addNotify () {
DockingAction.model.addNotify();
super.addNotify();
}
/** Notifies data model in adition to normal behaviour */
public void removeNotify () {
DockingAction.model.removeNotify();
super.removeNotify();
}
} // end of SpecialSubMenu
/** Implementation of SubMenuModel.
*/
static final class ActSubMenuModel implements Actions.SubMenuModel,
Serializable {
/** Caches a list of allowed modes for currently activated top comp
* @associates SpecialItem*/
transient List modeList;
/** Cached reference to the currently activated top component */
transient TopComponent comp;
static final long serialVersionUID =1811068881824983422L;
public int getCount() {
return modeList.size();
}
public String getLabel(int index) {
Object found = modeList.get(index);
if (found instanceof SpecialItem)
return ((SpecialItem)found).name;
if (found instanceof Mode)
return ((Mode)found).getDisplayName();
return null;
}
public HelpCtx getHelpCtx (int index) {
return null;
}
public MenuShortcut getMenuShortcut(int index) {
return null;
}
/** Actually performs the "docking" action by setting the mode
* of how component will be displayed
*/
public void performActionAt(int index) {
//System.out.println ("Performing action..."); // NOI18N
Object found = modeList.get(index);
if (found instanceof Mode) {
((Mode)found).dockInto(comp);
comp.requestFocus();
}
// special items
if (found instanceof SpecialItem) {
WorkspaceImpl curWorkspace =
(WorkspaceImpl)wm.getCurrentWorkspace();
// dock into specially created modes
Mode mode = null;
String modeName = null;
switch (((SpecialItem)found).type) {
case ModeImpl.SINGLE:
modeName = wm.findUnusedModeName(comp.getName(),
curWorkspace);
mode = curWorkspace.createMode(
modeName, modeName, null,
ModeImpl.SINGLE, true
);
break;
case ModeImpl.MULTI_TAB:
modeName = wm.findUnusedModeName(newMultiTabName,
curWorkspace);
mode = curWorkspace.createMode(
modeName, modeName, null, // PENDING - what to use ???
ModeImpl.MULTI_TAB, true
);
break;
}
mode.dockInto(comp);
}
// we can clear 'cause we know addNotify must be called
// before successive performActionAt
modeList = null;
comp = null;
}
/** Adds change listener for changes of the model.
*/
public void addChangeListener (ChangeListener l) {
}
/** Removes change listener for changes of the model.
*/
public void removeChangeListener (ChangeListener l) {
}
/** Called when a menu becomes visible.
* Loads the information about allowed modes of
* currently active top component
*/
void addNotify () {
//System.out.println ("Add notify..."); // NOI18N
comp = TopComponent.getRegistry ().getActivated ();
if (comp == null) {
modeList = new ArrayList(0);
return;
}
Set modes = TopManager.getDefault().getWindowManager().
getCurrentWorkspace().getModes();
int count = modes.size();
// obtain mode active top component is in
Workspace curWorkspace =
TopManager.getDefault().getWindowManager().getCurrentWorkspace();
Mode compMode = curWorkspace.findMode(comp);
// create mode list
modeList = new ArrayList(count + 3);
ArrayList userDefined = new ArrayList(count);
Mode curMode;
for (Iterator iter = modes.iterator(); iter.hasNext(); ) {
curMode = (Mode)iter.next();
if (curMode.canDock(comp) && (!curMode.equals(compMode))) {
if (((ModeImpl)curMode).isUserDefined()) {
// exclude used defined orphans
if (!((ModeImpl)curMode).isOrphan())
userDefined.add(curMode);
} else {
modeList.add(curMode);
}
}
}
// complete the modes and add separators (nulls)
modeList.add(null);
if (userDefined.size() > 0) {
boolean someAdded = false;
modeList.addAll(userDefined);
modeList.add(null);
}
if (!((ModeImpl)compMode).isSingle()) {
// allow docking to single only if in multi
modeList.add(NEW_SINGLE_ITEM);
}
// new multi mode
modeList.add(NEW_MULTI_TAB_ITEM);
}
/** Called when a presenter becomes invisible.
* Clears cached data.
*/
void removeNotify () {
//System.out.println ("Remove notify..."); // NOI18N
}
} // end of ActSubMenuModel
/** Simple structure to keep info about special items
* in docking menu */
static final class SpecialItem {
public String name;
public int type;
SpecialItem (String name, int type) {
this.name = name;
this.type = type;
}
}
}
/*
* Log
* 8 Gandalf 1.7 1/13/00 Jaroslav Tulach I18N
* 7 Gandalf 1.6 1/12/00 Ales Novak i18n
* 6 Gandalf 1.5 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 5 Gandalf 1.4 8/9/99 Ian Formanek Generated Serial Version
* UID
* 4 Gandalf 1.3 7/29/99 David Simonek further ws serialization
* changes
* 3 Gandalf 1.2 7/28/99 David Simonek workspace serialization
* bugfixes
* 2 Gandalf 1.1 7/21/99 David Simonek window system updates...
* 1 Gandalf 1.0 7/20/99 David Simonek
* $
*/